package pdfsetter.ui;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import pdfsetter.core.XMLObjectSerializer;
import pdfsetter.core.schema.DocumentSchema;
import pdfsetter.core.schema.DocumentSchemaPattern;
import pdfsetter.impl.pdfbox.compiler.PdfBoxDocumentCompiler;

/**
 * This is not very successful class for processing user commands.
 * 
 * @author Andrzej Dorobisz
 */
public class CommandLineInterface {
    private boolean parseArguments(String[] args, PartCommand[] partCommands) {
        HashMap<String, PartCommand> commands = new HashMap<String, PartCommand>();
        for (PartCommand cmd : partCommands) {
            commands.put(cmd.getName(), cmd);
        }
        int ind = 0;
        while (ind < args.length) {
            String curString = args[ind++];
            PartCommand cms = commands.remove(curString);
            if (cms == null)
                return false;
            if (cms.isInitialized())
                return false;
            int tmpInd = ind;
            while (tmpInd < args.length && !args[tmpInd].startsWith("-"))
                tmpInd++;
            if (!cms.setArgs(Arrays.copyOfRange(args, ind, tmpInd)))
                return false;
            ind = tmpInd;
        }
        if (commands.isEmpty())
            return true;
        else {
            commands.clear();
            return false;
        }
    }

    public void printUsage(PartCommand[] cmdTab) {
        System.out.println("Usage:");
        System.out.println("java -jar pdfsetter.jar <arguments>");
        System.out.println("You have to type all parameters:");
        for (PartCommand cmd : cmdTab)
            cmd.printUsage("\t");
        System.out.println("to set your pdf or you can use:");
        System.out.println("\t-examples [outputDirectory]");
        System.out.println("to save some templates on your disk.");

    }

    public void processCommand(String[] args) {
        OutCommand outCmd = new OutCommand();
        DocCommand docCmd = new DocCommand(new XMLObjectSerializer());
        FilesCommand filesCmd = new FilesCommand();
        PartCommand[] cmdTab = { outCmd, docCmd, filesCmd };

        if (args == null || args.length == 0 || args[0] == null) {
            printUsage(cmdTab);
            return;
        }
        if (args[0].equals("-examples")) {
            if (args.length == 1)
                new WriteExamples(new XMLObjectSerializer()).process(null);
            else if (args.length > 1)
                new WriteExamples(new XMLObjectSerializer()).process(args[1]);
            else
                printUsage(cmdTab);
            return;
        }

        if (!parseArguments(args, cmdTab)) {
            System.out.println("Arguments are incorrect.");
            printUsage(cmdTab);
            return;
        }
        try {
            DocumentSchemaPattern docPattern = docCmd.process();
            List<File> inputFiles = filesCmd.process();
            File outputFile = outCmd.process();
            if (Math.abs(docPattern.getExpectedNumberOfFiles()) > inputFiles.size()) {
                System.out.println("Too few input files for this document schema.");
                return;
            }
            int[] fileSizes = new PDFBasicManager().retrieveDocumentsSizes(inputFiles);
            if (fileSizes == null) {
                System.out.println("Cannot properly read files.");
                return;
            }
            DocumentSchema doc = docPattern.produceDocumentSchema(fileSizes);
            new PdfBoxDocumentCompiler().compile(doc, inputFiles, outputFile);
        } catch (ProcessCommandException e) {
            System.out.println("Error during processing command.");
        }
    }
}
